using System;
using System.Collections;
using UnityEngine;

namespace CinemaDirector
{
	[Serializable]
	[ExecuteInEditMode]
	public class Cutscene : MonoBehaviour
	{
		public enum CutsceneState
		{
			Inactive = 0,
			Playing = 1,
			PreviewPlaying = 2,
			Scrubbing = 3,
			Paused = 4
		}

		[SerializeField]
		private float duration = 30f;

		[SerializeField]
		private float runningTime;

		[SerializeField]
		public float playbackSpeed = 1f;

		[SerializeField]
		private CutsceneState state;

		public GGVariableStore variables = new GGVariableStore();

		private float previousTime;

		private Coroutine coroutine;

		protected TrackGroup[] trackGroups_;

		public float Duration
		{
			get
			{
				return duration;
			}
			set
			{
				duration = value;
				if (duration <= 0f)
				{
					duration = 0.1f;
				}
			}
		}

		public CutsceneState State
		{
			get
			{
				return state;
			}
		}

		public float RunningTime
		{
			get
			{
				return runningTime;
			}
			set
			{
				runningTime = Mathf.Clamp(value, 0f, duration);
			}
		}

		public TrackGroup[] TrackGroups
		{
			get
			{
				if (Application.isPlaying)
				{
					if (trackGroups_ == null)
					{
						trackGroups_ = GetComponentsInChildren<TrackGroup>();
					}
					return trackGroups_;
				}
				return GetComponentsInChildren<TrackGroup>();
			}
		}

		public DirectorGroup DirectorGroup
		{
			get
			{
				return GetComponentInChildren<DirectorGroup>();
			}
		}

		public event CutsceneHandler CutsceneFinished;

		public event CutsceneHandler CutscenePaused;

		public void PreviewPlay()
		{
			if (state == CutsceneState.Inactive)
			{
				EnterPreviewMode();
			}
			else if (state == CutsceneState.Paused)
			{
				resume();
			}
			state = CutsceneState.PreviewPlaying;
		}

		private void StartUpdateCoroutine()
		{
			StopUpdateCoroutine();
			coroutine = StartCoroutine(updateCoroutine());
		}

		private void StopUpdateCoroutine()
		{
			if (coroutine != null)
			{
				StopCoroutine(coroutine);
			}
		}

		public void Play()
		{
			base.gameObject.SetActive(true);
			StopAllCoroutines();
			if (state == CutsceneState.Inactive)
			{
				state = CutsceneState.Playing;
				initialize();
				UpdateCutscene(0f);
				StartUpdateCoroutine();
			}
			else if (state == CutsceneState.Paused)
			{
				state = CutsceneState.Playing;
				UpdateCutscene(0f);
				StartUpdateCoroutine();
			}
		}

		public void Pause()
		{
			if (state == CutsceneState.Playing)
			{
				StopUpdateCoroutine();
			}
			if (state == CutsceneState.PreviewPlaying || state == CutsceneState.Playing || state == CutsceneState.Scrubbing)
			{
				TrackGroup[] trackGroups = TrackGroups;
				foreach (TrackGroup trackGroup in trackGroups)
				{
					trackGroup.Pause();
				}
			}
			state = CutsceneState.Paused;
			if (this.CutscenePaused != null)
			{
				this.CutscenePaused(this, new CutsceneEventArgs());
			}
		}

		public void Stop()
		{
			state = CutsceneState.Inactive;
			RunningTime = 0f;
			TrackGroup[] trackGroups = TrackGroups;
			foreach (TrackGroup trackGroup in trackGroups)
			{
				trackGroup.Stop();
			}
			if (state == CutsceneState.Playing)
			{
				StopUpdateCoroutine();
			}
		}

		public void UpdateCutscene(float deltaTime)
		{
			float num = deltaTime * playbackSpeed;
			RunningTime += num;
			TrackGroup[] trackGroups = TrackGroups;
			foreach (TrackGroup trackGroup in trackGroups)
			{
				trackGroup.UpdateTrackGroup(runningTime, num);
			}
			if (runningTime >= duration || runningTime < 0f)
			{
				Stop();
				if (this.CutsceneFinished != null)
				{
					this.CutsceneFinished(this, new CutsceneEventArgs());
				}
			}
		}

		public void ScrubToTime(float newTime)
		{
			float deltaTime = newTime - RunningTime;
			state = CutsceneState.Scrubbing;
			UpdateCutscene(deltaTime);
		}

		public void SetRunningTime(float time)
		{
			RunningTime = time;
			TrackGroup[] trackGroups = TrackGroups;
			foreach (TrackGroup trackGroup in trackGroups)
			{
				trackGroup.SetRunningTime(RunningTime);
			}
		}

		public void EnterPreviewMode()
		{
			if (state == CutsceneState.Inactive)
			{
				initialize();
				TrackGroup[] trackGroups = TrackGroups;
				foreach (TrackGroup trackGroup in trackGroups)
				{
					trackGroup.SetRunningTime(RunningTime);
				}
				state = CutsceneState.Paused;
			}
		}

		public void ExitPreviewMode()
		{
			Stop();
		}

		private void initialize()
		{
			TrackGroup[] trackGroups = TrackGroups;
			foreach (TrackGroup trackGroup in trackGroups)
			{
				trackGroup.Initialize(this);
			}
		}

		private IEnumerator updateCoroutine()
		{
			while (state == CutsceneState.Playing)
			{
				UpdateCutscene(Time.deltaTime);
				yield return null;
			}
		}

		private void resume()
		{
			TrackGroup[] trackGroups = TrackGroups;
			foreach (TrackGroup trackGroup in trackGroups)
			{
				trackGroup.Resume();
			}
		}
	}
}
